package com.zhang.novel.listener;

import com.zhang.novel.core.cache.CacheKey;
import com.zhang.novel.core.cache.CacheService;
import com.zhang.novel.core.utils.Constants;
import com.zhang.novel.service.BookService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.nio.channels.Channel;

@Component
@Slf4j
@ConditionalOnProperty(prefix = "spring.rabbitmq", name = "enable", havingValue = "1")
@RequiredArgsConstructor
public class AddVisitCountListener {

    private final CacheService cacheService;

    private final BookService bookService;

    /**
     * 更新点击量到数据库
     * 流量削峰
     *
     * @param bookId
     */
    @RabbitListener(queues = "UPDATE-DB-QUEUE")       // 由于在配置类中，已经将交换机与消息队列绑定，所以只选用监听消息队列，即可消费消息
    public void updateDbConsumer(Long bookId) {
        log.debug("更新点击量到数据库  bookID===" + bookId);

        //TODO 操作共享资源visitCount，集群环境下有线程安全问题，引入Redisson框架实现分布式锁

        // 缓存中获取累积的点击量
        Integer visitCount = (Integer) cacheService.getObject(CacheKey.BOOK_ADD_VISIT_COUNT);

        // 不存在，则初始化为0
        if (null == visitCount) {
            visitCount = 0;
        }
        // 对缓存中的累积量进行自增
        cacheService.setObject(CacheKey.BOOK_ADD_VISIT_COUNT,++visitCount);

        // 累积后，判断累积是否达到预定值
        if(visitCount>=Constants.ADD_MAX_VISIT_COUNT){
            // 说明累积量与达到预定值，需要更新到数据库
            bookService.addVisitCount(bookId,visitCount);
            // 清除累积的缓存
            cacheService.delete(CacheKey.BOOK_ADD_VISIT_COUNT);
        }

    }
}
